from classfile.constant import ConstantPool, ConstantHelper
from heap.system_ref import ClassRef, MethodRef, FieldRef, InterfaceMethodRef
from utils.numer_utils import math


class KlassConstantPool:
    def __init__(self, klass, constantPool: ConstantPool):
        self.cp = [None]
        self.klass = klass

        def skip_math_constant(index, data):
            c = data.getConstant(index=index)
            if c.tag == ConstantHelper.CONSTANT_INTEGER or c.tag == ConstantHelper.CONSTANT_FLOAT \
                    or c.tag == ConstantHelper.CONSTANT_LONG or c.tag == ConstantHelper.CONSTANT_DOUBLE \
                    or c.tag == ConstantHelper.CONSTANT_UTF_8 or c.tag == ConstantHelper.CONSTANT_STRING:
                self.cp.append({'value': c.value, 'tag': c.tag})
            elif c.tag == ConstantHelper.CONSTANT_CLASS:
                ref = ClassRef(className=c.className, cp=self)
                self.cp.append(ref)
            elif c.tag == ConstantHelper.CONSTANT_METHOD_REF:
                ref = MethodRef(className=None, cp=self)
                ref.copyMethod(c)
                self.cp.append(ref)
            elif c.tag == ConstantHelper.CONSTANT_FIELD_REF:
                ref = FieldRef(className=None, cp=self)
                ref.copyField(c)
                self.cp.append(ref)
            elif c.tag == ConstantHelper.CONSTANT_INTERFACE_METHOD_REF:
                ref = InterfaceMethodRef(className=None, cp=self)
                ref.copyMethod(c)
                self.cp.append(ref)
            else:
                # print("not support constant type:{}".format(c.tag))
                self.cp.append(c)
            if c.slotCount > 1:
                self.cp.append(None)
                return True
            return False

        math.for_skip_range(rg=range(1, constantPool.size),
                            data=constantPool,
                            fn=skip_math_constant)

    def getConstant2(self, index):
        return self.cp[index]

    def getConstantValue(self, index):
        c = self.cp[index]
        if type(c) == map:
            return c['value']
        return c

    def getKlass(self):
        return self.klass
